package com.server;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import tratamentoNotificacoes.NotificationObserver;
import tratamentoNotificacoes.StateObservable;
import acessoDados.Singleton;
import acessoDados.dao.BaseDAO;
import constants.ProjectConstants;
import core.Director;
import core.PessoaFactoryMethod;
import core.Reserva;
import core.Viagem;

public class ServerParser {

	@SuppressWarnings({ "unused", "static-access","rawtypes" })
	public String parser(String b) throws ClassNotFoundException, SQLException, JDOMException, IOException {

		System.out.println("[RECEBI ISTO]" + b);

		SAXBuilder builder = new SAXBuilder(); // The document handler
		Element root; // Elements and attributes to read XML file
		Document doc = new Document();

		doc = builder.build(new ByteArrayInputStream(b.getBytes()));
		root = doc.getRootElement();

		Element type = root.getChild("type");

		if (root.getChild("type").getAttributeValue("op").equalsIgnoreCase("get")) {

			// CASE LOGIN
			if (type.getChild("what").getAttributeValue("id").equals("login")) {
				
				String login = type.getChild("what").getChild("login").getValue();
				
				String pass = type.getChild("what").getChild("password").getValue();
				String passNaBD = Singleton.getInstance().getPessoaDAO().getPass(login);
				
				int funcao = Integer.parseInt(type.getChild("what").getChild("funcao").getValue());				
				int funcaoNaBD = Integer.parseInt(Singleton.getInstance().getPessoaDAO().getFuncao(login));

				if (pass.equals(passNaBD) && funcao<=funcaoNaBD) {
					// return XMLServerResponses.sendReply("ok", "login", "0",type.getChild("what").getChild("username").getValue());
					return "ok";
				} else {
					// return XMLServerResponses.sendReply("fail", "login", "0", type.getChild("what").getChild("username").getValue());
					return "fail";
				}

			}

			// case register
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("register")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String bi = type.getChild("what").getChild("bi").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();

//				Singleton.getInstance().getPessoaDAO().criaPessoa(login, password, bi, nome, email, telemovel, "" + ProjectConstants.CLIENTE);
				new PessoaFactoryMethod().criaPessoa(login, password, bi, nome, email, telemovel, ProjectConstants.CLIENTE);
				
				return XMLServerResponses.sendReply("ok", "register", "0", type.getChild("what").getChild("login").getValue());

			}

			// case addFuncionario
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addFuncionario")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String bi = type.getChild("what").getChild("bi").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();
				String funcao = type.getChild("what").getChild("funcao").getValue();

//				Singleton.getInstance().getPessoaDAO().criaPessoa(login, password, bi, nome, email, telemovel, funcao);
				new PessoaFactoryMethod().criaPessoa(login, password, bi, nome, email, telemovel, Integer.parseInt(funcao));
				
				return "ok";
			}

			// case addTripulante
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addTripulante")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String bi = type.getChild("what").getChild("bi").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();
				String funcao = type.getChild("what").getChild("funcao").getValue();

//				Singleton.getInstance().getPessoaDAO().criaPessoa(login, password, bi, nome, email, telemovel, funcao);
				new PessoaFactoryMethod().criaPessoa(login, password, bi, nome, email, telemovel, Integer.parseInt(funcao));
				
				return "ok";
			}

			// case addViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addViagem")) {

				String partida = type.getChild("what").getChild("partida").getValue();
				String chegada = type.getChild("what").getChild("chegada").getValue();
				String aviao = type.getChild("what").getChild("aviao").getValue().split("_")[0];
				String preco = type.getChild("what").getChild("preco").getValue();
				
				Director director = new Director();
				return director.constructViagem(partida, chegada, aviao, preco,type.getChild("what").getChild("locais").getChildren("local").toArray(),
												type.getChild("what").getChild("tripulacao").getChildren("user").toArray());
				
			}

			// case addAviao
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addAviao")) {

				String nome = type.getChild("what").getChild("nome").getValue();
				String lotacao = type.getChild("what").getChild("lotacao").getValue();

				Singleton.getInstance().getAviaoDAO().criaAviao(nome, Integer.parseInt(lotacao));

				return "ok";
			}

			// case addReserva
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addReserva")) {

				String login = type.getChild("what").getChild("user").getValue();
				String viagem = type.getChild("what").getChild("viagem").getValue();
				String pagamento = type.getChild("what").getChild("pagamento").getValue();

				BaseDAO dao = Singleton.getInstance();

				Director director = new Director();
				return director.constructReserva(login, Integer.parseInt(viagem), pagamento,type.getChild("what").getChild("lugares").getChildren("lugar").toArray());
				
			}

			// case editFuncionario
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editFuncionario")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String loginAnterior = type.getChild("what").getChild("loginAnterior").getValue();
				String bi = type.getChild("what").getChild("bi").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();
				String funcao = type.getChild("what").getChild("funcao").getValue();

				Singleton.getInstance().getPessoaDAO().editPessoa(loginAnterior, login, password, bi, nome, email, telemovel, funcao);

				return "ok";
			}

			// case editTripulante
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editTripulante")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String loginAnterior = type.getChild("what").getChild("loginAnterior").getValue();

				String bi = type.getChild("what").getChild("bi").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();
				String funcao = type.getChild("what").getChild("funcao").getValue();

				Singleton.getInstance().getPessoaDAO().editPessoa(loginAnterior, login, password, bi, nome, email, telemovel, funcao);

				return "ok";
			}

			// case editClient
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editClient")) {

				String nome = type.getChild("what").getChild("name").getValue();
				String password = type.getChild("what").getChild("password").getValue();
				String login = type.getChild("what").getChild("login").getValue();
				String loginAnterior = type.getChild("what").getChild("loginAnterior").getValue();
				String bi = type.getChild("what").getChild("bi").getValue();
				String email = type.getChild("what").getChild("email").getValue();
				String telemovel = type.getChild("what").getChild("telemovel").getValue();
				String funcao = type.getChild("what").getChild("funcao").getValue();

				Singleton.getInstance().getPessoaDAO().editPessoa(loginAnterior, login, password, bi, nome, email, telemovel, funcao);
				
				return "ok";
			}

			// case editAviao
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editAviao")) {

				String id = type.getChild("what").getChild("id").getValue();
				String nome = type.getChild("what").getChild("nome").getValue();
				String lotacao = type.getChild("what").getChild("lotacao").getValue();

				Singleton.getInstance().getAviaoDAO().editAviao(id, nome, lotacao);

				return "ok";
			}

			// case removeFuncionario
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("removeFuncionario")) {

				String id = type.getChild("what").getChild("user").getValue();

				Singleton.getInstance().getPessoaDAO().deletePessoa(id);

				return "ok";
			}

			// case removeTripulante
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("removeTripulante")) {

				String id = type.getChild("what").getChild("user").getValue();

				Singleton.getInstance().getPessoaDAO().deletePessoa(id);

				return "ok";
			}

			// case removeCliente
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("removeCliente")) {

				String id = type.getChild("what").getChild("user").getValue();

				Singleton.getInstance().getPessoaDAO().deletePessoa(id);

				return "ok";
			}

			// case removeAviao
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("removeAviao")) {

				String id = type.getChild("what").getChild("aviao").getValue();

				Singleton.getInstance().getAviaoDAO().deleteAviao(id);

				return "ok";
			}

			// case cancelaViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("cancelaViagem")) {
				
				String id = type.getChild("what").getChild("viagem").getValue();
				
				ResultSet rs = Singleton.getInstance().getViagemDAO().getViagem(id);
				Viagem viagem = new Viagem();
				
				if(rs.next()){
					viagem.setIdViagem(Integer.parseInt(id));
					viagem.setIdAviao(""+rs.getInt("idAviao"));
					viagem.setPartida(""+rs.getInt("diaPartida"));
					viagem.setChegada(""+rs.getInt("diaChegada"));
					viagem.setPreco(rs.getInt("preco"));
					viagem.setState(rs.getInt("estadoViagem"));
				}
				
				if(viagem.cancelaViagem()==1)				
					return "ok";
				else
					return "fail";
			}

			// case cancelaReserva
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("cancelaReserva")) {
				
				String id = type.getChild("what").getChild("reserva").getValue();
				
				ResultSet rs = Singleton.getInstance().getReservaDAO().getReserva(id);
				Reserva reserva = new Reserva();
				
				if(rs.next()){
					reserva.setIdReserva(Integer.parseInt(id));
					reserva.setIdViagem(rs.getInt("idViagem"));
					reserva.setLogin(rs.getString("login"));
					reserva.setTipoPagamento(rs.getString("tipoPagamento"));
					reserva.setQuantPagamento(rs.getInt("quantPagamento"));
					reserva.setState(rs.getInt("estadoReserva"));
				}
				
				if(reserva.cancelaReserva()==1)				
					return "ok";
				else
					return "fail";
			}

			// case getFuncionarios
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getFuncionarios")) {

				return XMLServerResponses.sendFuncionarios(Singleton.getInstance().getPessoaDAO().getFuncionarios());
			}

			// case getDetalhesFuncionario
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesFuncionario")) {

				String id = type.getChild("what").getChild("user").getValue();

				return XMLServerResponses.sendDetalhesFuncionario(Singleton.getInstance().getPessoaDAO().getDetalhesFuncionario(id));
			}

			// case getRelatorios
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getRelatorios")) {

				return XMLServerResponses.sendRelatorios(Singleton.getInstance().getRelatorioDAO().getRelatorios());
			}

			// case getNotificacoes
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getNotificacoes")) {

				String id = type.getChild("what").getChild("user").getValue();

				return XMLServerResponses.sendNotificacoes(Singleton.getInstance().getNotificacaoDAO().getNotificacoes(id));
			}

			// case getReservas
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getReservas")) {

				String id = type.getChild("what").getChild("user").getValue();

				return XMLServerResponses.sendReservas(Singleton.getInstance().getReservaDAO().getReservas(id));
			}

			// case getDetalhesReserva
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesReserva")) {

				String id = type.getChild("what").getChild("reserva").getValue();

				return XMLServerResponses.sendDetalhesReserva(Singleton.getInstance().getReservaDAO().getDetalhesReserva(id));
			}

			// case getViagens
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getViagens")) {

				return XMLServerResponses.sendViagens(Singleton.getInstance().getViagemDAO().getViagens());
			}

			// case getDetalhesViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesViagem")) {

				String id = type.getChild("what").getChild("viagem").getValue();

				return XMLServerResponses.sendDetalhesViagem(Singleton.getInstance().getViagemDAO().getDetalhesViagem(id));
			}

			// case getClientes
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getClientes")) {

				return XMLServerResponses.sendClientes(Singleton.getInstance().getPessoaDAO().getClientes());
			}

			// case getDetalhesCliente
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesCliente")) {

				String id = type.getChild("what").getChild("user").getValue();

				return XMLServerResponses.sendDetalhesCliente(Singleton.getInstance().getPessoaDAO().getDetalhesCliente(id));
			}

			// case getTripulacao
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getTripulacao")) {

				return XMLServerResponses.sendTripulantes(Singleton.getInstance().getPessoaDAO().getTripulantes());
			}

			// case getDetalhesTripulante
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesTripulante")) {

				String id = type.getChild("what").getChild("user").getValue();

				return XMLServerResponses.sendDetalhesTripulante(Singleton.getInstance().getPessoaDAO().getDetalhesTripulante(id));
			}

			// case getAvioes
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getAvioes")) {

				return XMLServerResponses.sendAvioes(Singleton.getInstance().getAviaoDAO().getAvioes());
			}

			// case getDetalhesAviao
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesAviao")) {

				return XMLServerResponses.sendDetalhesAviao(Singleton.getInstance().getAviaoDAO().getDetalhesAviao(type.getChild("what").getChild("aviao").getValue()));
			}

			// case getLocais
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getLocais")) {

				return XMLServerResponses.sendLocais(Singleton.getInstance().getLocalDAO().getLocais());
			}

			// case removeLocal
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("removeLocal")) {

				Singleton.getInstance().getLocalDAO().removeLocal(type.getChild("what").getChild("local").getValue());
				
				return "ok";
			}

			// case addLocal
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("addLocal")) {

				String nome = type.getChild("what").getChild("nome").getValue();
				int coordX = Integer.parseInt(type.getChild("what").getChild("coordx").getValue());
				int coordY = Integer.parseInt(type.getChild("what").getChild("coordy").getValue());

				Singleton.getInstance().getLocalDAO().criaLocal(coordX, coordY, nome);

				return "ok";
			}
			
			// case getDetalhesLocal
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getDetalhesLocal")) {

				return XMLServerResponses.sendDetalhesLocal(Singleton.getInstance().getLocalDAO().getDetalhesLocal(type.getChild("what").getChild("local").getValue()));
			}

			// case editLocal
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editLocal")) {

				int id = Integer.parseInt(type.getChild("what").getChild("id").getValue());
				String nome = type.getChild("what").getChild("nome").getValue();
				int coordX = Integer.parseInt(type.getChild("what").getChild("coordx").getValue());
				int coordY = Integer.parseInt(type.getChild("what").getChild("coordy").getValue());

				Singleton.getInstance().getLocalDAO().editLocal(id, coordX, coordY, nome);

				return "ok";
			}

			// case getLocaisViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getLocaisViagem")) {

				String id = type.getChild("what").getChild("viagem").getValue();

				return XMLServerResponses.sendLocaisViagem(Singleton.getInstance().getViagemDAO().getLocaisViagem(id));
			}

			// case getTripulantesViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getTripulantesViagem")) {

				String id = type.getChild("what").getChild("viagem").getValue();

				return XMLServerResponses.sendTripulantesViagem(Singleton.getInstance().getViagemDAO().getTripulantesViagem(id));
			}

			// case editViagem
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("editViagem")) {

				int idViagem = Integer.parseInt( type.getChild("what").getChild("id").getValue() );
				String partida = type.getChild("what").getChild("partida").getValue();
				String chegada = type.getChild("what").getChild("chegada").getValue();
				String aviao = type.getChild("what").getChild("aviao").getValue().split("_")[0];
				String preco = type.getChild("what").getChild("preco").getValue();

				String tripulacao = type.getChild("what").getChild("tripulacao").getValue();
				String[] cadaTripulante = tripulacao.split(",");

				BaseDAO dao = Singleton.getInstance();
				
				dao.getViagemDAO().editViagem(idViagem, partida, chegada, aviao, preco);
				
				//locais e local
				dao.getViagemDAO().desassociaLocais(idViagem);
				int i=0;
				
				
				Iterator iterator= type.getChild("what").getChild("locais").getChildren("local").iterator();
				while(iterator.hasNext()){
					Object local=iterator.next();
					dao.getViagemDAO().associaLocal(idViagem, Integer.parseInt( ((Element)local).getText().split("_")[0] ), i++);
				}

				//tripulacao e user
				dao.getViagemDAO().desassociaTripulantes(idViagem);
				iterator= type.getChild("what").getChild("tripulacao").getChildren("user").iterator();
				while(iterator.hasNext()){
					Object user=iterator.next();
					dao.getViagemDAO().associaTripulante(idViagem,  ((Element)user).getText() );
				}

				ResultSet rs = dao.getReservaDAO().getReservasDeViagem(""+idViagem);
				StateObservable stObs = new StateObservable();
				while(rs.next()){
					int idReserva = rs.getInt("idReserva");
					
					//adiciona observer ao observable
					NotificationObserver notifObs = new NotificationObserver(idReserva, true);
					stObs.addObserver(notifObs);					
				}
				//notifica observers
				stObs.notifica(""+idViagem);
				return "ok";
			}

			// case getLugaresReservados
			else if (type.getChild("what").getAttributeValue("id").equalsIgnoreCase("getLugaresReservados")) {

				String id = type.getChild("what").getChild("viagem").getValue();

				return XMLServerResponses.sendLugaresReservados(Singleton.getInstance().getViagemDAO().getLugaresReservadosViagem(id));
			}

		}

		return "NOT A GET FUNCTION";
	}

}
